home *** CD-ROM | disk | FTP | other *** search
/ Planet Source Code Jumbo …e CD Visual Basic 1 to 7 / 5_2007-2008.ISO / data / Zips / DTMF_detec20367512102006.psc / DTMF Detector / Form1.frm next >
Text File  |  2006-12-10  |  13KB  |  415 lines

  1. VERSION 5.00
  2. Object = "{831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0"; "mscomctl.ocx"
  3. Begin VB.Form Form1 
  4.    BorderStyle     =   1  'Fest Einfach
  5.    Caption         =   "DTMF Detector"
  6.    ClientHeight    =   3210
  7.    ClientLeft      =   45
  8.    ClientTop       =   330
  9.    ClientWidth     =   4485
  10.    BeginProperty Font 
  11.       Name            =   "Tahoma"
  12.       Size            =   8.25
  13.       Charset         =   0
  14.       Weight          =   400
  15.       Underline       =   0   'False
  16.       Italic          =   0   'False
  17.       Strikethrough   =   0   'False
  18.    EndProperty
  19.    LinkTopic       =   "Form1"
  20.    MaxButton       =   0   'False
  21.    MinButton       =   0   'False
  22.    ScaleHeight     =   3210
  23.    ScaleWidth      =   4485
  24.    StartUpPosition =   3  'Windows-Standard
  25.    Begin VB.Timer tmr 
  26.       Enabled         =   0   'False
  27.       Interval        =   100
  28.       Left            =   3750
  29.       Top             =   1725
  30.    End
  31.    Begin MSComctlLib.StatusBar sbar 
  32.       Align           =   2  'Unten ausrichten
  33.       Height          =   240
  34.       Left            =   0
  35.       TabIndex        =   10
  36.       Top             =   2970
  37.       Width           =   4485
  38.       _ExtentX        =   7911
  39.       _ExtentY        =   423
  40.       Style           =   1
  41.       SimpleText      =   "Ready"
  42.       _Version        =   393216
  43.       BeginProperty Panels {8E3867A5-8586-11D1-B16A-00C0F0283628} 
  44.          NumPanels       =   1
  45.          BeginProperty Panel1 {8E3867AB-8586-11D1-B16A-00C0F0283628} 
  46.          EndProperty
  47.       EndProperty
  48.    End
  49.    Begin VB.Frame frmNumber 
  50.       Caption         =   "Dialed:"
  51.       Height          =   915
  52.       Left            =   225
  53.       TabIndex        =   8
  54.       Top             =   1875
  55.       Width           =   3990
  56.       Begin VB.Label lblNumber 
  57.          BeginProperty Font 
  58.             Name            =   "Tahoma"
  59.             Size            =   15.75
  60.             Charset         =   0
  61.             Weight          =   400
  62.             Underline       =   0   'False
  63.             Italic          =   0   'False
  64.             Strikethrough   =   0   'False
  65.          EndProperty
  66.          Height          =   465
  67.          Left            =   150
  68.          TabIndex        =   9
  69.          Top             =   300
  70.          Width           =   3690
  71.       End
  72.    End
  73.    Begin VB.CommandButton cmdStop 
  74.       Cancel          =   -1  'True
  75.       Caption         =   "Stop Recording"
  76.       Enabled         =   0   'False
  77.       Height          =   345
  78.       Left            =   2925
  79.       TabIndex        =   7
  80.       Top             =   1350
  81.       Width           =   1290
  82.    End
  83.    Begin VB.CommandButton cmdStart 
  84.       Caption         =   "Start Recording"
  85.       Default         =   -1  'True
  86.       Height          =   345
  87.       Left            =   1575
  88.       TabIndex        =   6
  89.       Top             =   1350
  90.       Width           =   1290
  91.    End
  92.    Begin MSComctlLib.Slider sldVol 
  93.       Height          =   270
  94.       Left            =   975
  95.       TabIndex        =   5
  96.       Top             =   900
  97.       Width           =   3240
  98.       _ExtentX        =   5715
  99.       _ExtentY        =   476
  100.       _Version        =   393216
  101.       Max             =   65535
  102.       TickStyle       =   3
  103.    End
  104.    Begin VB.ComboBox cboRecLine 
  105.       Height          =   315
  106.       Left            =   975
  107.       Style           =   2  'Dropdown-Liste
  108.       TabIndex        =   3
  109.       Top             =   525
  110.       Width           =   3240
  111.    End
  112.    Begin VB.ComboBox cboRecDev 
  113.       Height          =   315
  114.       Left            =   975
  115.       Style           =   2  'Dropdown-Liste
  116.       TabIndex        =   1
  117.       Top             =   150
  118.       Width           =   3240
  119.    End
  120.    Begin VB.Label lblVolume 
  121.       Caption         =   "Volume:"
  122.       Height          =   240
  123.       Left            =   225
  124.       TabIndex        =   4
  125.       Top             =   900
  126.       Width           =   765
  127.    End
  128.    Begin VB.Label lblLine 
  129.       Caption         =   "Line:"
  130.       Height          =   240
  131.       Left            =   225
  132.       TabIndex        =   2
  133.       Top             =   525
  134.       Width           =   690
  135.    End
  136.    Begin VB.Label lblDev 
  137.       Caption         =   "Device:"
  138.       Height          =   240
  139.       Left            =   225
  140.       TabIndex        =   0
  141.       Top             =   150
  142.       Width           =   840
  143.    End
  144. End
  145. Attribute VB_Name = "Form1"
  146. Attribute VB_GlobalNameSpace = False
  147. Attribute VB_Creatable = False
  148. Attribute VB_PredeclaredId = True
  149. Attribute VB_Exposed = False
  150. Option Explicit
  151.  
  152. Private Const samplerate            As Long = 22050
  153. Private Const Channels              As Long = 1
  154. Private Const SILENCE_THRESHOLD     As Long = 30
  155. Private Const BUFSILENCE_THRESHOLD  As Long = 60
  156.  
  157. Private Const BUFFER_LENGTH         As Long = 10
  158.  
  159. Private Const PI                    As Single = 3.14159265358979
  160. Private Const PI2                   As Single = PI * 2
  161. Private Const LOG10                 As Single = 0.434294481903251
  162. Private Const NODIVZ                As Single = 0.000000000000001
  163.  
  164. Private DTMF_F1()                   As Single
  165. Private DTMF_F2()                   As Single
  166. Private DTMF_NUM()                  As Single
  167.  
  168. Private WithEvents m_clsRecorder    As WaveInRecorder
  169. Attribute m_clsRecorder.VB_VarHelpID = -1
  170.  
  171. Private m_lngRecorded               As Long
  172. Private m_blnGotSilence             As Boolean
  173.  
  174. ' Dual Tone Multi-Frequency (DTMF) Tabelle (ITU-T Q.23)
  175. '
  176. ' Hz          1209    1336    1477    1633
  177. ' 697          1       2       3       A
  178. ' 770          4       5       6       B
  179. ' 852          7       8       9       C
  180. ' 941          *       0       #       D
  181. '
  182. Private Sub FillDTMFTable()
  183.     Dim i   As Integer
  184.     Dim j   As Integer
  185.     Dim k   As Integer
  186.  
  187.     ReDim DTMF_F1(3) As Single
  188.     ReDim DTMF_F2(3) As Single
  189.     ReDim DTMF_NUM(15, 3) As Single
  190.  
  191.     DTMF_F1(0) = 697: DTMF_F2(0) = 1209
  192.     DTMF_F1(1) = 770: DTMF_F2(1) = 1336
  193.     DTMF_F1(2) = 852: DTMF_F2(2) = 1477
  194.     DTMF_F1(3) = 941: DTMF_F2(3) = 1633
  195.  
  196.     ReDim DTMF_NUM(15, 2) As Single
  197.  
  198.     For i = 0 To UBound(DTMF_F1)
  199.         For j = 0 To UBound(DTMF_F2)
  200.             DTMF_NUM(k, 0) = DTMF_F1(i)
  201.             DTMF_NUM(k, 1) = DTMF_F2(j)
  202.             k = k + 1
  203.         Next
  204.     Next
  205.  
  206.     DTMF_NUM(0, 2) = Asc("1")
  207.     DTMF_NUM(1, 2) = Asc("2")
  208.     DTMF_NUM(2, 2) = Asc("3")
  209.     DTMF_NUM(3, 2) = Asc("A")
  210.     DTMF_NUM(4, 2) = Asc("4")
  211.     DTMF_NUM(5, 2) = Asc("5")
  212.     DTMF_NUM(6, 2) = Asc("6")
  213.     DTMF_NUM(7, 2) = Asc("B")
  214.     DTMF_NUM(8, 2) = Asc("7")
  215.     DTMF_NUM(9, 2) = Asc("8")
  216.     DTMF_NUM(10, 2) = Asc("9")
  217.     DTMF_NUM(11, 2) = Asc("C")
  218.     DTMF_NUM(12, 2) = Asc("*")
  219.     DTMF_NUM(13, 2) = Asc("0")
  220.     DTMF_NUM(14, 2) = Asc("#")
  221.     DTMF_NUM(15, 2) = Asc("D")
  222. End Sub
  223.  
  224. Private Sub cboRecDev_Click()
  225.     Dim i   As Long
  226.     
  227.     cboRecLine.Clear
  228.     
  229.     If Not m_clsRecorder.SelectDevice(cboRecDev.ListIndex) Then
  230.         MsgBox "Couldn't select device!", vbExclamation
  231.         Exit Sub
  232.     End If
  233.     
  234.     For i = 0 To m_clsRecorder.MixerLineCount - 1
  235.         cboRecLine.AddItem m_clsRecorder.MixerLineName(i)
  236.     Next
  237.     cboRecLine.ListIndex = 0
  238. End Sub
  239.  
  240. Private Sub cboRecLine_Click()
  241.     If Not m_clsRecorder.SelectMixerLine(cboRecLine.ListIndex) Then
  242.         MsgBox "Couldn't select Mixer Line!", vbExclamation
  243.         Exit Sub
  244.     End If
  245.     
  246.     sldVol.value = m_clsRecorder.MixerLineVolume
  247. End Sub
  248.  
  249. Private Sub cmdStart_Click()
  250.     lblNumber.Caption = ""
  251.     
  252.     If Not m_clsRecorder.StartRecord(samplerate, Channels) Then
  253.         MsgBox "Couldn't start recording with " & samplerate & " Hz, " & Channels & " Channels!", vbExclamation
  254.         Exit Sub
  255.     End If
  256.     
  257.     tmr.Enabled = True
  258.     
  259.     cmdStart.Enabled = False
  260.     cmdStop.Enabled = True
  261. End Sub
  262.  
  263. Private Sub cmdStop_Click()
  264.     If Not m_clsRecorder.StopRecord() Then
  265.         MsgBox "Couldn't properly stop recording!"
  266.     End If
  267.     
  268.     m_lngRecorded = 0
  269.     tmr.Enabled = False
  270.     sbar.SimpleText = "Ready"
  271.     
  272.     cmdStart.Enabled = True
  273.     cmdStop.Enabled = False
  274. End Sub
  275.  
  276. Private Sub Form_Load()
  277.     Dim i   As Long
  278.     
  279.     Set m_clsRecorder = New WaveInRecorder
  280.     
  281.     ' 10 ms buffersize so we can detect silence between numbers
  282.     m_clsRecorder.BufferSize = MSToBytes(BUFFER_LENGTH)
  283.     
  284.     For i = 0 To m_clsRecorder.DeviceCount - 1
  285.         cboRecDev.AddItem m_clsRecorder.DeviceName(i)
  286.     Next
  287.     cboRecDev.ListIndex = 0
  288.     
  289.     FillDTMFTable
  290. End Sub
  291.  
  292. Private Sub Form_Unload(Cancel As Integer)
  293.     m_clsRecorder.StopRecord
  294. End Sub
  295.  
  296. Private Sub m_clsRecorder_GotData(intBuffer() As Integer, lngLen As Long)
  297.     Dim lngAmplitude    As Single, lngPartCount     As Long
  298.     Dim lngMaxAmplitude As Single, lngMaxAmplitude2 As Single
  299.     Dim sngMaxF1        As Single, sngMaxF2         As Single
  300.     Dim sngSamples()    As Single
  301.     Dim i               As Long
  302.     
  303.     m_lngRecorded = m_lngRecorded + BytesToMS(lngLen)
  304.     
  305.     ReDim sngSamples(lngLen \ 2 - 1) As Single
  306.     
  307.     For i = 0 To lngLen \ 2 - 1
  308.         ' normalize all 16 bit samples to floats ([-1;+1])
  309.         sngSamples(i) = intBuffer(i) / 32768
  310.         
  311.         ' sum up all the positive amplitudes in the signal buffer
  312.         If intBuffer(i) > 0 Then
  313.             lngMaxAmplitude = lngMaxAmplitude + intBuffer(i)
  314.             lngPartCount = lngPartCount + 1
  315.         End If
  316.     Next
  317.     
  318.     ' no positive amplitudes?
  319.     If lngPartCount = 0 Then Exit Sub
  320.     
  321.     ' get the power of the average amplitude of the signal to detect silence
  322.     If power(lngMaxAmplitude / lngPartCount) < BUFSILENCE_THRESHOLD Then
  323.         m_blnGotSilence = True
  324.         Exit Sub
  325.     End If
  326.     lngMaxAmplitude = 0
  327.  
  328.     ' find the first DTMF frequency
  329.     For i = 0 To UBound(DTMF_F1)
  330.         lngAmplitude = power(Goertzel(sngSamples, 0, lngLen \ 2, DTMF_F1(i), samplerate))
  331.  
  332.         If lngAmplitude > lngMaxAmplitude Then
  333.             lngMaxAmplitude = lngAmplitude
  334.             sngMaxF1 = DTMF_F1(i)
  335.         End If
  336.     Next
  337.  
  338.     ' find the second DTMF frequency
  339.     For i = 0 To UBound(DTMF_F2)
  340.         lngAmplitude = power(Goertzel(sngSamples, 0, lngLen \ 2, DTMF_F2(i), samplerate))
  341.  
  342.         If lngAmplitude > lngMaxAmplitude2 Then
  343.             lngMaxAmplitude2 = lngAmplitude
  344.             sngMaxF2 = DTMF_F2(i)
  345.         End If
  346.     Next
  347.     
  348.     ' if we just had silence then this could be valid
  349.     If m_blnGotSilence Then
  350.         ' check if the found frequencies are powerful
  351.         If lngMaxAmplitude > SILENCE_THRESHOLD And lngMaxAmplitude2 > SILENCE_THRESHOLD Then
  352.             ' get the sign the frequencies match with
  353.             For i = 0 To UBound(DTMF_NUM)
  354.                 If DTMF_NUM(i, 0) = sngMaxF1 Then
  355.                     If DTMF_NUM(i, 1) = sngMaxF2 Then
  356.                         lblNumber.Caption = lblNumber.Caption & Chr$(DTMF_NUM(i, 2))
  357.                         Exit For
  358.                     End If
  359.                 End If
  360.             Next
  361.             ' expect silence
  362.             m_blnGotSilence = False
  363.         End If
  364.     End If
  365. End Sub
  366.  
  367. Private Sub sldVol_Scroll()
  368.     m_clsRecorder.MixerLineVolume = sldVol.value
  369. End Sub
  370.  
  371. Private Function BytesToMS(ByVal bytes As Long) As Long
  372.     BytesToMS = bytes / (samplerate * Channels * 2) * 1000
  373. End Function
  374.  
  375. Private Function MSToBytes(ByVal ms As Long) As Long
  376.     MSToBytes = ms / 1000 * (samplerate * Channels * 2)
  377. End Function
  378.  
  379. Private Sub tmr_Timer()
  380.     sbar.SimpleText = "Recording... " & FmtTime(m_lngRecorded)
  381. End Sub
  382.  
  383. Private Function FmtTime(ByVal ms As Long) As String
  384.     FmtTime = ((ms / 1000) \ 60) & ":" & Format((ms / 1000) Mod 60, "00")
  385. End Function
  386.  
  387. ' amplitude to Decibel
  388. Private Function power(ByVal value As Single) As Single
  389.     power = 20 * Log(Abs(value) + NODIVZ) * LOG10
  390. End Function
  391.  
  392. ' like a Fourier Transformation for 1 frequency
  393. '
  394. ' source:
  395. ' http://www.musicdsp.org/archive.php?classid=0#107
  396. Function Goertzel(sngData() As Single, ByVal S As Long, ByVal N As Long, ByVal freq As Single, ByVal sampr As Long) As Single
  397.     Dim Skn     As Single
  398.     Dim Skn1    As Single
  399.     Dim Skn2    As Single
  400.     Dim c       As Single
  401.     Dim c2      As Single
  402.     Dim i       As Long
  403.  
  404.     c = PI2 * freq / sampr
  405.     c2 = Cos(c)
  406.  
  407.     For i = S To S + N - 1
  408.         Skn2 = Skn1
  409.         Skn1 = Skn
  410.         Skn = 2 * c2 * Skn1 - Skn2 + sngData(i)
  411.     Next
  412.  
  413.     Goertzel = Skn - Exp(-c) * Skn1
  414. End Function
  415.